import { Request, Response, NextFunction } from 'express';
import ApiResponse from '@/utils/api/api-response.util';
import { isEmpty, isValidStatus, isValidCron } from '../common/validation.util';
import { getLogger } from '@/utils/logger';
import { AuthRequest } from '@/types';
import SchedulerUtils from '@/utils/job/scheduler.util';

const logger = getLogger('job-validator', { console: false });
const consoleLogger = getLogger('job-validator');

/**
 * 验证定时任务详情参数
 */
export const validateJobDetail = async (req: Request, res: Response, next: NextFunction) => {
  try {
    const jobId = parseInt(req.params.jobId, 10);
    
    if (isNaN(jobId) || jobId <= 0) {
      consoleLogger.warn('获取定时任务详情参数无效', { jobId: req.params.jobId });
      return ApiResponse.error(res, '无效的任务ID', 400);
    }
    
    logger.debug('定时任务详情参数验证通过');
    next();
    return;
  } catch (error) {
    consoleLogger.error(`定时任务详情验证失败: ${error instanceof Error ? error.message : String(error)}`);
    return ApiResponse.error(res, '参数验证失败', 500);
  }
};

/**
 * 验证定时任务创建参数
 */
export const validateJobCreate = async (req: AuthRequest, res: Response, next: NextFunction) => {
  try {
    const { jobName, jobGroup, invokeTarget, cronExpression } = req.body;
    
    // 任务名称验证
    if (isEmpty(jobName)) {
      return ApiResponse.error(res, '任务名称不能为空', 400);
    }
    
    // 任务组名验证
    if (isEmpty(jobGroup)) {
      return ApiResponse.error(res, '任务组名不能为空', 400);
    }
    
    // 调用目标验证
    if (isEmpty(invokeTarget)) {
      return ApiResponse.error(res, '调用目标不能为空', 400);
    }
    
    // Cron表达式验证
    if (isEmpty(cronExpression)) {
      return ApiResponse.error(res, 'Cron表达式不能为空', 400);
    }
    
    if (!isValidCron(cronExpression)) {
      return ApiResponse.error(res, 'Cron表达式格式不正确', 400);
    }
    
    // 验证调用目标是否在白名单中
    if (!SchedulerUtils.whiteList(invokeTarget)) {
      consoleLogger.warn('新增任务失败: 目标字符串不在白名单内', { invokeTarget });
      return ApiResponse.error(res, '目标字符串不在白名单内', 400);
    }
    
    // 检查调用目标是否包含禁止的字符串
    const dangerPatterns = ['rmi', 'ldap', 'ldaps', 'http', 'https'];
    if (dangerPatterns.some(pattern => invokeTarget.toLowerCase().includes(pattern))) {
      consoleLogger.warn('新增任务失败: 目标字符串包含禁止的模式', { invokeTarget });
      return ApiResponse.error(res, '目标字符串包含禁止的模式', 400);
    }
    
    logger.debug('定时任务创建参数验证通过');
    next();
    return;
  } catch (error) {
    consoleLogger.error(`定时任务创建验证失败: ${error instanceof Error ? error.message : String(error)}`);
    return ApiResponse.error(res, '参数验证失败', 500);
  }
};

/**
 * 验证定时任务更新参数
 */
export const validateJobUpdate = async (req: AuthRequest, res: Response, next: NextFunction) => {
  try {
    const { jobId, jobName, jobGroup, invokeTarget, cronExpression } = req.body;
    
    // ID验证
    if (isEmpty(jobId) || isNaN(parseInt(jobId))) {
      return ApiResponse.error(res, '任务ID不能为空或无效', 400);
    }
    
    // 任务名称验证
    if (isEmpty(jobName)) {
      return ApiResponse.error(res, '任务名称不能为空', 400);
    }
    
    // 任务组名验证
    if (isEmpty(jobGroup)) {
      return ApiResponse.error(res, '任务组名不能为空', 400);
    }
    
    // 调用目标验证
    if (isEmpty(invokeTarget)) {
      return ApiResponse.error(res, '调用目标不能为空', 400);
    }
    
    // Cron表达式验证
    if (isEmpty(cronExpression)) {
      return ApiResponse.error(res, 'Cron表达式不能为空', 400);
    }
    
    if (!isValidCron(cronExpression)) {
      return ApiResponse.error(res, 'Cron表达式格式不正确', 400);
    }
    
    // 验证调用目标是否在白名单中
    if (!SchedulerUtils.whiteList(invokeTarget)) {
      consoleLogger.warn('修改任务失败: 目标字符串不在白名单内', { invokeTarget });
      return ApiResponse.error(res, '目标字符串不在白名单内', 400);
    }
    
    // 检查调用目标是否包含禁止的字符串
    const dangerPatterns = ['rmi', 'ldap', 'ldaps', 'http', 'https'];
    if (dangerPatterns.some(pattern => invokeTarget.toLowerCase().includes(pattern))) {
      consoleLogger.warn('修改任务失败: 目标字符串包含禁止的模式', { invokeTarget });
      return ApiResponse.error(res, '目标字符串包含禁止的模式', 400);
    }
    
    logger.debug('定时任务更新参数验证通过');
    next();
    return;
  } catch (error) {
    consoleLogger.error(`定时任务更新验证失败: ${error instanceof Error ? error.message : String(error)}`);
    return ApiResponse.error(res, '参数验证失败', 500);
  }
};

/**
 * 验证定时任务状态修改参数
 */
export const validateJobChangeStatus = async (req: Request, res: Response, next: NextFunction) => {
  try {
    const { jobId, status } = req.body;
    
    // ID验证
    if (isEmpty(jobId) || isNaN(parseInt(jobId))) {
      return ApiResponse.error(res, '任务ID不能为空或无效', 400);
    }
    
    // 状态验证
    if (isEmpty(status)) {
      return ApiResponse.error(res, '状态不能为空', 400);
    }
    
    if (!isValidStatus(status)) {
      return ApiResponse.error(res, '状态值无效', 400);
    }
    
    logger.debug('定时任务状态修改参数验证通过');
    next();
    return;
  } catch (error) {
    consoleLogger.error(`定时任务状态修改验证失败: ${error instanceof Error ? error.message : String(error)}`);
    return ApiResponse.error(res, '参数验证失败', 500);
  }
};

/**
 * 验证定时任务执行参数
 */
export const validateJobRun = async (req: Request, res: Response, next: NextFunction) => {
  try {
    const { jobId } = req.body;
    
    // ID验证
    if (isEmpty(jobId) || isNaN(parseInt(jobId))) {
      return ApiResponse.error(res, '任务ID不能为空或无效', 400);
    }
    
    logger.debug('定时任务执行参数验证通过');
    next();
    return;
  } catch (error) {
    consoleLogger.error(`定时任务执行验证失败: ${error instanceof Error ? error.message : String(error)}`);
    return ApiResponse.error(res, '参数验证失败', 500);
  }
};

/**
 * 验证定时任务删除参数
 */
export const validateJobRemove = async (req: Request, res: Response, next: NextFunction) => {
  try {
    const { jobIds } = req.params;
    
    if (isEmpty(jobIds)) {
      return ApiResponse.error(res, '任务ID不能为空', 400);
    }
    
    const ids = jobIds.split(',').map(id => parseInt(id));
    
    if (ids.some(id => isNaN(id))) {
      return ApiResponse.error(res, '任务ID格式无效', 400);
    }
    
    logger.debug('定时任务删除参数验证通过');
    next();
    return;
  } catch (error) {
    consoleLogger.error(`定时任务删除验证失败: ${error instanceof Error ? error.message : String(error)}`);
    return ApiResponse.error(res, '参数验证失败', 500);
  }
}; 